import json

from flask_restful import Resource
from flask import current_app, request, g
from flask_restful.reqparse import RequestParser

from comment.modules import db
from comment.modules.account import Account
from comment.utils.SendMessage import send_sms
from comment.modules.user import User
from comment.utils.decorators import login_required
from comment.utils.financial_redis import fr
from comment.utils.tokens_pyjwt import generate_tokens, verify_tokens
from financial.resources.account import AccountInfoSerializer
from financial.resources.user import constants
from financial.resources.user.serializer import InvitedListSerializer, UserInfoSerializer


class Login(Resource):
    """
    登录
    """

    def post(self):

        rp = RequestParser()
        rp.add_argument('username', required=True)
        rp.add_argument('password', required=True)
        args = rp.parse_args()
        username = args.username  # 用户
        password = args.password  # 密码

        user = User.query.filter(User.username == username).first()
        if user:
            # 验证密码是否
            if user.check_password(password):
                # 用户登录成功，之后生产一个token，以便于后面去认真token
                token = generate_tokens(user.id)
                current_app.logger.info(token)
                current_app.logger.info('测试验证token', verify_tokens(token))
                return {'token': token}
        return {'message': '用户名或者密码错误。', 'code': 20001}


class LoginOut(Resource):
    """
        退出登录
        """
    # 使用登录的拦截器

    def post(self):
        if g.user_id:
            g.user_id = None
        return {'msg': '成功退出登录'}


class UserAvatar(Resource):
    """
    管理用户的头像
    """
    # 使用了登录拦截的装饰器
    method_decorators = [login_required]

    def post(self):
        """
        上传用户头像图片
        :return:
        """

        # 用户上传的图片数据
        img_data = request.files['file']

        id = g.user_id
        user = User.query.filter(User.id == id).first()

        # 设置用户头像图片保存的路径
        img_dir = current_app.config['AVATAR_DIR']
        # 设置图像文件的名字
        img_name = str(id) + '_' + img_data.filename

        file_path = img_dir + '/' + img_name

        # 保存文件
        try:
            img_data.save(file_path)
        except Exception as e:
            current_app.logger.error(e)
            return {'message': '头像文件上传失败！'}

        # 在数据库中保持用户头像图片的文件名
        if user:
            user.avatar = img_name
            db.session.commit()
            return {'msg': '上传头像图片成功', 'avatar': img_name}


class RegisterUser(Resource):
    """
    用户的注册
    """

    def post(self):
        rp = RequestParser()
        rp.add_argument('phone', required=True)
        rp.add_argument('username', required=True)
        rp.add_argument('password', required=True)
        rp.add_argument('code', required=True)
        rp.add_argument('invite_code')

        args = rp.parse_args()
        username = args.username
        password = args.password
        phone = args.phone
        code = args.code
        invite_code = args.invite_code

        # 验证用户名是否唯一
        u = User.query.filter(User.username == username).first()
        if u:  # 用户名存在
            current_app.logger.info('{}:用户名已经存在，请更换用户名'.format(username))
            return {'message': '用户名重复', 'code': 20001}

        # 从Redis数据库中获取之前保存的验证码
        real_code = fr.get('registerCode:{}'.format(code))
        if not real_code or real_code.decode() != code:  # 数据库中没有code或者存储的code和参数不一致
            current_app.logger.info('验证码错误或者时效')
            return {'message': '验证码错误或者时效.', 'code': 20001}

        # 把用户保存到Mysql数据库中
        u = User(username=username, phone=phone, pwd=password)

        # 验证和关联邀请码
        if invite_code:
            self.check_invite(u, invite_code)

        try:  # 需要用到数据库事务处理
            db.session.add(u)
            db.session.flush()  # 把数据插入数据库的缓冲区（得到自增ID）。并不是插入到数据库中
            account = Account(userId=u.id)  # 创建当前用户的账户对象。
            db.session.add(account)
            db.session.commit()
            return {'msg': 'success'}
        except Exception as ex:
            current_app.logger.error(ex)
            db.session.rollback()
            return {'message': '用户注册时，插入数据库失败', 'code': 20001}

    # 验证和关联邀请码
    def check_invite(self, user, invite_code):
        code = invite_code.strip()
        invite_user = User.query.filter(User.inviteId == code).first()
        if invite_user:
            user.invite_user_id = invite_user.id  # 如果邀请码有效，则把这两个用户关联一下
            invite_user.accountInfo.discount += constants.INVITE_MONEY  # 邀请用户的账户中增加50元的代金券
            invite_user.sumFriends = invite_user.sumFriends + 1 if invite_user.sumFriends else 1  # 邀请的记录数 增加一个


class IsExistPhone(Resource):
    """
    判断手机号是否存在
    """

    def post(self):
        phone = request.json.get('phone')
        user = User.query.filter(User.phone == phone).first()
        if user:
            return {'message': "此手机号已经注册过，请更换手机号", 'code': 20001}
        return {'msg': 'success'}


class SmsCode(Resource):
    """
    发送手机验证码
    """

    def get(self):
        phone = request.args['phone'].strip()
        import random
        code = random.randint(1000, 9999)
        # result = send_sms(phone, str(code))
        # re_dict = json.loads(result)
        # re_dict['phone'] = phone

        fr.setex('registerCode:{}'.format(code), constants.SMS_CODE_EXPIRES, code)
        return {"msg": "success", "smsCode": code}


class Invite(Resource):
    """邀请码奖励管理的资源"""

    # 使用登录奖励的拦截器
    method_decorators = [login_required]

    def post(self):
        """生成邀请码"""

        u_id = g.user_id
        user = User.query.filter(User.id == u_id).first()
        # 根据用户名，采用uuid算法生成一个唯一邀请码
        import uuid
        invite_code = str(uuid.uuid5(uuid.NAMESPACE_DNS, user.username))
        user.inviteId = invite_code
        db.session.commit()
        return {'msg': 'success', 'invite_code': invite_code}

    def get(self):
        """查询被邀请人的列表"""
        u_id = g.user_id

        # 查询被邀请的人
        invited_list = User.query.filter(User.invite_user_id == u_id).all()
        if invited_list:
            data = InvitedListSerializer(invited_list).to_dict()
            return {'msg': 'success', 'list': data}
        else:
            return {'msg': 'success', 'list': []}


class LoginPwd(Resource):
    """
    修改登录密码
    """

    # 设置登录验证
    method_decorators = [login_required]

    def post(self):
        rp = RequestParser()
        rp.add_argument('orgPwd', required=True)
        rp.add_argument('pwd', required=True)
        args = rp.parse_args()
        pwd = args.pwd
        # 原始密码
        orgPwd = args.orgPwd
        id = g.user_id
        user = User.query.filter(User.id == id).first()

        if user:
            if user.check_password(orgPwd):
                user.pwd = pwd
                db.session.commit()
                return {'msg': 'success'}
            else:
                return {'code': 20002, 'message': '原密码不正确'}


class UserInfo(Resource):
    """用户信息资源类"""
    method_decorators = [login_required]

    def get(self):
        """当前登录用户的查询，包括 所有关联的账户数据"""
        u_id=g.user_id
        user=User.query.filter(User.id==u_id).first()
        user_info_data=UserInfoSerializer(user).to_dict()
        #查询当前用户所对应的账户信息
        acc=Account.query.filter(Account.userId==u_id).first()

        acc_data={}
        if acc:
            acc_data=AccountInfoSerializer(acc).to_dict()

        return {
            'roles': ['admin'] if user.role else ['user'],
            'name': user.username,
            'userInfoData': user_info_data,
            'accountInfo': acc_data
            }


class RealNameAuth(Resource):
    """
    实名认证
    """

    method_decorators = [login_required]

    def post(self):
        rp = RequestParser()
        rp.add_argument('realName', required=True)
        rp.add_argument('idNum', required=True)
        args = rp.parse_args()
        realName = args.realName   # 真实姓名
        idNum = args.idNum         # 身份证ID
        id = g.user_id
        user = User.query.filter(User.id == id).first()
        if user.realName:
            return {"code": 20001, 'message': '不可重复验证'}
        else:
            user.realName = realName  # 名字
            user.realNameStatus = 1  # 实名状态
            user.idNum = idNum  # 身份证
            db.session.commit()
            return {'msg': 'success'}


class PayPassword(Resource):
    """
    设置支付密码
    """

    # 设置登录验证
    method_decorators = [login_required]

    def post(self):
        rp = RequestParser()
        rp.add_argument('pwd', required=True)
        args = rp.parse_args()
        pwd = args.pwd
        id = g.user_id
        user = User.query.filter(User.id == id).first()
        if user:
            user.pay_pwd = pwd
            user.payPwdStatus = 1
            db.session.commit()
            return {'msg': 'success'}


